package tw.org;

import java.io.*;
import java.net.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.json.*;
import org.w3c.dom.*;

/**
 *
 * @author P-C Lin
 */
public class W3C {

	private HttpServletRequest request = null;
	private HttpServletResponse response = null;
	private HttpSession session = null;
	private Locale locale = null;
	private HttpServlet servlet = null;

	public void setServlet(HttpServlet httpServlet) {
		servlet = httpServlet;
	}

	//---------------------------------------------------------------------
	/**
	 * 沒啥好說的！
	 *
	 * @param httpServletRequest 啊丟係 request 咩
	 */
	public void setRequest(HttpServletRequest httpServletRequest) throws UnsupportedEncodingException {
		request = httpServletRequest;
		if (request != null) {
			request.setCharacterEncoding("UTF-8");
			if (request.getHeader("accept-language").length() > 1) {
				for (String acceptLanguage : request.getHeader("accept-language").split(",")) {
					String languageCountry = acceptLanguage.replaceAll(";.*$", "");
					if (languageCountry.length() == 5) {
						setLocale(languageCountry.split("-")[0].toLowerCase(), languageCountry.split("-")[1].toUpperCase());
						return;
					}
				}
			}
		}
		setLocale("zh", "TW");
	}

	/**
	 * 沒啥好說的！
	 *
	 * @return 就 request 咩。
	 */
	public HttpServletRequest getRequest() {
		return request;
	}

	/**
	 * 請求方式是否為 GET？
	 *
	 * @return 如請求方式為 GET 則回傳 true；否則回傳 false。
	 */
	public boolean isGet() {
		return request.getMethod().equalsIgnoreCase("GET");
	}

	/**
	 * 請求是否含檔案上傳？
	 *
	 * @return 如請求含檔案上傳則回傳 true；否則回傳 false。
	 */
	public boolean isMultipartContent() {
		return org.apache.commons.fileupload.servlet.ServletFileUpload.isMultipartContent(request);
	}

	/**
	 * 請求方式是否為 POST？
	 *
	 * @return 如請求方式為 POST 則回傳 true；否則回傳 false。
	 */
	public boolean isPost() {
		return request.getMethod().equalsIgnoreCase("POST");
	}

	/**
	 * 名稱為 name 的參數是否存在？
	 *
	 * @param name 參數名稱
	 * @return 如存在則回傳 true；否則回傳 false。
	 */
	public boolean hasParameter(String name) {
		return request.getParameter(name) != null;
	}

	/**
	 * 名稱為 name 的參數是否為 null？
	 *
	 * @param name 參數名稱
	 * @return 如為 null 則回傳 true；否則回傳 false。
	 */
	public boolean isParameterEmpty(String name) {
		return (request.getParameter(name).isEmpty());
	}

	/**
	 * 取得名稱為 name 的 request 參數值。
	 *
	 * @param name 參數名稱
	 * @return 如該參數存在且不為空則回傳該參數值；否則回傳 null。
	 */
	public String getParameter(String name) {
		if (hasParameter(name) && !isParameterEmpty(name)) {
			return request.getParameter(name);
		}
		return null;
	}

	/**
	 * 取得名稱為 name 的 request 參數值陣列。
	 *
	 * @param name 參數名稱
	 * @return 如該參數存在且不為空則回傳該參數值陣列；否則回傳 null。
	 */
	public String[] getParameters(String name) {
		return request.getParameterValues(name);
	}

	/**
	 * 取得參考來源。
	 *
	 * @return 參考來源網址
	 */
	public String getReferer() {
		return request.getHeader("referer");
	}

	/**
	 * 取得參考來源。
	 *
	 * @return 檔案名稱
	 * @throws MalformedURLException
	 */
	public String getRefererFile() throws MalformedURLException {
		return new URL(getReferer()).getFile();
	}

	/**
	 * 取得參考來源的主機名稱。
	 *
	 * @return 主機名稱
	 * @throws MalformedURLException
	 */
	public String getRefererHost() throws MalformedURLException {
		return new URL(getReferer()).getHost();
	}

	/**
	 * 取得參考來源的路徑。
	 *
	 * @return 路徑
	 * @throws MalformedURLException
	 */
	public String getRefererPath() throws MalformedURLException {
		return new URL(getReferer()).getPath();
	}

	/**
	 * 取得參考來源的通訊埠。
	 *
	 * @return 通訊埠
	 * @throws MalformedURLException
	 */
	public int getRefererPort() throws MalformedURLException {
		return new URL(getReferer()).getPort();
	}

	/**
	 * 取得參考來源的協定。
	 *
	 * @return 協定
	 * @throws MalformedURLException
	 */
	public String getRefererProtocol() throws MalformedURLException {
		return new URL(getReferer()).getProtocol();
	}

	/**
	 * 取得參考來源的查詢字串。
	 *
	 * @return 查詢字串
	 * @throws MalformedURLException
	 */
	public String getRefererQuery() throws MalformedURLException {
		return new URL(getReferer()).getQuery();
	}

	/**
	 * 取得遠端 IP 位址。
	 *
	 * @return IP 位址。
	 */
	public String getRemoteAddr() {
		return request.getRemoteAddr();
	}

	/**
	 * 取得遠端主機名稱。
	 *
	 * @return 主機名稱。
	 */
	public String getRemoteHost() {
		return request.getRemoteHost();
	}

	/**
	 * 取得遠端通訊埠。
	 *
	 * @return 通訊埠。
	 */
	public int getRemotePort() {
		return request.getRemotePort();
	}

	/**
	 * 取得遠端使用者。
	 *
	 * @return 使用者。
	 */
	public String getRemoteUser() {
		return request.getRemoteUser();
	}

	//---------------------------------------------------------------------
	/**
	 * 沒啥好說的！
	 *
	 * @param httpServletResponse 啊丟係 response 咩
	 */
	public void setResponse(HttpServletResponse httpServletResponse) {
		response = httpServletResponse;
		if (response != null) {
			response.setCharacterEncoding("UTF-8");
		}
	}

	/**
	 * 沒啥好說的！
	 *
	 * @return 就 response 咩。
	 */
	public HttpServletResponse getResponse() {
		return response;
	}

	/**
	 * 取得 out 物件。
	 *
	 * @return out 物件
	 * @throws IOException
	 */
	public ServletOutputStream getOutputStream() throws IOException {
		return response.getOutputStream();
	}

	/**
	 * 取得 PrintWriter 物件。
	 *
	 * @return PrintWriter 物件
	 * @throws IOException
	 */
	public PrintWriter getWriter() throws IOException {
		return response.getWriter();
	}

	/**
	 * 重導向！
	 *
	 * @param location 新的位址
	 * @throws IOException
	 */
	public void sendRedirect(String location) throws IOException {
		response.sendRedirect(location);
	}

	/**
	 * 設定回應的類型。
	 *
	 * @param type 內容類型
	 */
	public void setContentType(String type) {
		response.setContentType(type);
	}

	//---------------------------------------------------------------------
	/**
	 * 沒啥好說的！
	 *
	 * @param httpSession 啊丟係 session 咩
	 */
	public void setSession(HttpSession httpSession) {
		session = httpSession;
	}

	/**
	 * 沒啥好說的！
	 *
	 * @return 就 session 咩。
	 */
	public HttpSession getSession() {
		return session;
	}

	/**
	 * 設定 session 變數(物件)。
	 *
	 * @param name 變數(物件)名稱
	 * @param value 變數值(物件)
	 */
	public void setAttribute(String name, Object value) {
		session.setAttribute(name, value);
	}

	/**
	 * 名稱為 name 的 session 變數是否存在？
	 *
	 * @param name 變數(物件)名稱
	 * @return 如存在則回傳 true；否則回傳 false。
	 */
	public boolean hasAttribute(String name) {
		return session.getAttribute(name) != null;
	}

	/**
	 * 名稱為 name 的 session 變數(物件)是否為 null？
	 *
	 * @param name 變數(物件)名稱
	 * @return 如為 null 則回傳 true；否則回傳 false。
	 */
	public boolean isAttributeEmpty(String name) {
		return session.getAttribute(name) == null;
	}

	/**
	 * 取得名稱為 name 的 session 變數(物件)。
	 *
	 * @param name 變數(物件)名稱
	 * @return 如該變數(物件)存在且不為空則回傳該變數(物件)；否則回傳 null。
	 */
	public Object getAttribute(String name) {
		if (hasAttribute(name) && !isAttributeEmpty(name)) {
			return session.getAttribute(name);
		}
		return null;
	}

	/**
	 * 設定 session 待命週期
	 *
	 * @param interval session 待命週期(秒)
	 */
	public void setMaxInactiveInterval(int interval) {
		session.setMaxInactiveInterval(interval);
	}

	/**
	 * 取得 session 待命週期
	 *
	 * @return session 待命週期(秒)
	 */
	public int getMaxInactiveInterval() {
		return session.getMaxInactiveInterval();
	}

	/**
	 * 取得 session 的 id。
	 *
	 * @return session 的 id。
	 */
	public String getSessionId() {
		return session.getId();
	}

	//---------------------------------------------------------------------
	/**
	 * 設定語系。
	 *
	 * @param language 語碼
	 * @param country 國碼
	 */
	public void setLocale(String language, String country) {
		locale = new Locale(language, country);
	}

	/**
	 * 取得語系。
	 *
	 * @return 目前的語系。
	 */
	public Locale getLocale() {
		return locale;
	}

	/**
	 * 自動取得對應的國際化 XSL。
	 *
	 * @return 國際化後的 XSL。
	 */
	public StreamSource getLocalizedXsl() {
		return getLocalizedXsl(request.getRequestURI().replaceFirst("^" + request.getContextPath(), "").replaceFirst("\\.jsp$", ""));
	}

	/**
	 * 取得對應至 path 的國際化 XSL。
	 *
	 * @param path
	 * @return 與 path 相對應的國際化 XSL。
	 */
	public StreamSource getLocalizedXsl(String path) {
		return new StreamSource(getResourceAsStream("/" + locale.getLanguage().toLowerCase() + "-" + locale.getCountry().toUpperCase() + path + ".xsl"));
	}

	/**
	 * 取得指定的資源。
	 *
	 * @param name 資源包的名稱
	 * @return 與 name 相對應的 InputStream。
	 */
	public InputStream getResourceAsStream(String name) {
		return getClass().getResourceAsStream(name);
	}

	/**
	 * 轉換為國際化後的字串。
	 *
	 * @param baseName
	 * @param key
	 * @return
	 */
	public String toI18n(String baseName, String key) {
		return ResourceBundle.getBundle(baseName, locale).getString(key);
	}

	//---------------------------------------------------------------------
	/**
	 * 取得空時戳。
	 *
	 * @return 空白的時戳。
	 */
	public Calendar newCalendar() {
		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		return calendar;
	}

	/**
	 * 取得指定的時戳。
	 *
	 * @param year 年
	 * @param month 月
	 * @param date 日
	 * @return 取得指定的時戳。
	 */
	public Calendar newCalendar(int year, int month, int date) {
		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(year, month, date);
		return calendar;
	}

	/**
	 * 取得指定的時戳。
	 *
	 * @param year 年
	 * @param month 月
	 * @param date 日
	 * @param hourOfDay 時
	 * @param minute 分
	 * @return 取得指定的時戳。
	 */
	public Calendar newCalendar(int year, int month, int date, int hourOfDay, int minute) {
		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(year, month, date, hourOfDay, minute);
		return calendar;
	}

	/**
	 * 取得指定的時戳。
	 *
	 * @param year 年
	 * @param month 月
	 * @param date 日
	 * @param hourOfDay 時
	 * @param minute 分
	 * @param second 秒
	 * @return 取得指定的時戳。
	 */
	public Calendar newCalendar(int year, int month, int date, int hourOfDay, int minute, int second) {
		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(year, month, date, hourOfDay, minute, second);
		return calendar;
	}

	/**
	 * 取得指定的時戳。
	 *
	 * @param year 年
	 * @param month 月
	 * @param date 日
	 * @param hourOfDay 時
	 * @param minute 分
	 * @param second 秒
	 * @param millisecond 毫秒
	 * @return 取得指定的時戳。
	 */
	public Calendar newCalendar(int year, int month, int date, int hourOfDay, int minute, int second, int millisecond) {
		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(year, month, date, hourOfDay, minute, second);
		calendar.set(Calendar.MILLISECOND, millisecond);
		return calendar;
	}

	//---------------------------------------------------------------------
	/**
	 * 建立新的 XML 文件。
	 *
	 * @return 新的 XML 文件。
	 * @throws ParserConfigurationException
	 */
	public Document newDocument() throws ParserConfigurationException {
		return DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
	}

	/**
	 * 在指定的 element 下附加 CDATA。
	 *
	 * @param string CDATA 的內容。
	 * @param element 被附加的 element。
	 * @throws ParserConfigurationException
	 */
	public void appendCDATASection(String string, Element element) throws ParserConfigurationException {
		element.appendChild(element.getOwnerDocument().createCDATASection(string));
	}

	/**
	 * 自動將 document 和所對應的 XSL 轉換為 HTML 格式輸出。
	 *
	 * @param document
	 * @throws IOException
	 * @throws TransformerConfigurationException
	 * @throws TransformerException
	 */
	public void toHTML(Document document) throws IOException, TransformerConfigurationException, TransformerException {
		toHTML(document, getLocalizedXsl());
	}

	/**
	 * 將 document 和 path 所對應的 XSL 轉換為 HTML 格式輸出。
	 *
	 * @param document
	 * @param path
	 * @throws IOException
	 * @throws TransformerConfigurationException
	 * @throws TransformerException
	 */
	public void toHTML(Document document, String path) throws IOException, TransformerConfigurationException, TransformerException {
		toHTML(document, getLocalizedXsl(path));
	}

	/**
	 * 將 document 和 source 轉換為 HTML 格式輸出。
	 *
	 * @param document
	 * @param source
	 * @throws IOException
	 * @throws TransformerConfigurationException
	 * @throws TransformerException
	 */
	public void toHTML(Document document, Source source) throws IOException, TransformerConfigurationException, TransformerException {
		setContentType("text/html");
//		Transformer transformer = TransformerFactory.newInstance().newTransformer();
//		transformer.setURIResolver(new org.apache.fop.servlet.ServletContextURIResolver(servlet.getServletContext()));
//		transformer.transform(new DOMSource(document), new StreamResult(getOutputStream()));
		TransformerFactory.newInstance().newTransformer(source).transform(new DOMSource(document), new StreamResult(getOutputStream()));
	}

	/**
	 * 將 document 以 XML 格式輸出。
	 *
	 * @param document
	 * @throws IOException
	 * @throws TransformerConfigurationException
	 * @throws TransformerException
	 */
	public void toXML(Document document) throws IOException, TransformerConfigurationException, TransformerException {
		setContentType("text/xml");
		TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document), new StreamResult(getOutputStream()));
	}

	//---------------------------------------------------------------------
	/**
	 * 建立新的 JSON 陣列物件。
	 *
	 * @return 新的 JSON 陣列物件。
	 */
	public JSONArray newJSONArray() {
		return new JSONArray();
	}

	/**
	 * 建立新的 JSON 物件。
	 *
	 * @return 新的 JSON 物件。
	 */
	public JSONObject newJSONObject() {
		return new JSONObject();
	}
}